﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Windows;
using System.Windows.Media;
using CuteRibs.D3Armory.Models;
using CuteRibs.D3Armory.Resources;
using CuteRibs.MVVMLib;

namespace CuteRibs.D3Armory.ViewModels
{
	public class ItemViewModel : ViewModelBase
	{
		#region fields & properties
		private static readonly Dictionary<string, string> weaponElements;

		public Item Item { get; set; }
		private string backgroundUri;
		private string weaponElement;
		private SolidColorBrush borderBrush;
		private string itemUri;
		private Thickness slotOffset, iconOffset;
		private double slotWidth, slotHeight;
		private double iconWidth, iconHeight;

		public string BackgroundUri
		{
			get { return this.backgroundUri; }
			set
			{
				if (this.backgroundUri != value)
				{
					this.backgroundUri = value;
					this.NotifyPropertyChanged("BackgroundUri");
				}
			}
		}

		public string WeaponElement
		{
			get { return this.weaponElement; }
			set
			{
				if (this.weaponElement != value)
				{
					this.weaponElement = value;
					this.NotifyPropertyChanged("WeaponElement");
				}
			}
		}

		public SolidColorBrush BorderBrush
		{
			get { return this.borderBrush; }
			set
			{
				if (this.borderBrush != value)
				{
					this.borderBrush = value;
					this.NotifyPropertyChanged("BorderBrush");
				}
			}
		}

		public string ItemUri
		{
			get { return this.itemUri; }
			set
			{
				if (this.itemUri != value)
				{
					this.itemUri = value;
					this.NotifyPropertyChanged("ItemUri");
				}
			}
		}

		public Thickness SlotOffset
		{
			get { return this.slotOffset; }
			set
			{
				if (this.slotOffset != value)
				{
					this.slotOffset = value;
					this.NotifyPropertyChanged("SlotOffset");
				}
			}
		}

		public Thickness IconOffset
		{
			get { return this.iconOffset; }
			set
			{
				if (this.iconOffset != value)
				{
					this.iconOffset = value;
					this.NotifyPropertyChanged("IconOffset");
				}
			}
		}

		public double SlotWidth
		{
			get { return this.slotWidth; }
			set
			{
				if (this.slotWidth != value)
				{
					this.slotWidth = value;
					this.NotifyPropertyChanged("SlotWidth");
				}
			}
		}

		public double SlotHeight
		{
			get { return this.slotHeight; }
			set
			{
				if (this.slotHeight != value)
				{
					this.slotHeight = value;
					this.NotifyPropertyChanged("SlotHeight");
				}
			}
		}

		public double IconWidth
		{
			get { return this.iconWidth; }
			set
			{
				if (this.iconWidth != value)
				{
					this.iconWidth = value;
					this.NotifyPropertyChanged("IconWidth");
				}
			}
		}

		public double IconHeight
		{
			get { return this.iconHeight; }
			set
			{
				if (this.iconHeight != value)
				{
					this.iconHeight = value;
					this.NotifyPropertyChanged("IconHeight");
				}
			}
		}

		public ObservableCollection<SocketViewModel> Sockets { get; set; }
		#endregion

		static ItemViewModel()
		{
			weaponElements = new Dictionary<string, string>();
			weaponElements.Add("Damage_Weapon_Min#Fire", "fire");
			weaponElements.Add("Damage_Weapon_Min#Cold", "cold");
			weaponElements.Add("Damage_Weapon_Min#Lightning", "lightning");
			weaponElements.Add("Damage_Weapon_Min#Poison", "poison");
			weaponElements.Add("Damage_Weapon_Min#Arcane", "arcane");
			weaponElements.Add("Damage_Weapon_Min#Holy", "holy");
		}

		public ItemViewModel(Item item = null)
		{
			this.Item = item;
			this.Initialize();
		}

		protected void Initialize()
		{
			this.Sockets = new ObservableCollection<SocketViewModel>();

			if (this.Item != null)
			{
				this.BackgroundUri = string.Format("/Resources/Images/{0}.png", this.Item.DisplayColor);

				if(this.Item.ItemSlot.In(ItemSlot.MainHand, ItemSlot.OffHand))
				{
					this.WeaponElement = string.Format("/Resources/Images/{0}.png", this.SetWeaponElement(this.Item.AttributesRaw));
				}

				this.BorderBrush = GetBorderBrush(this.Item.DisplayColor);
				this.ItemUri = App.GetItemImageUri(this.Item.Icon);
				this.SetOffset(this.Item.ItemSlot);

				if (this.Item.AttributesRaw != null && this.Item.AttributesRaw.ContainsKey("Sockets"))
				{
					for (var i = 0; i < this.Item.AttributesRaw["Sockets"].Max; i++)
					{
						this.Sockets.Add(new SocketViewModel(this.Item.Gems, i));
					}
				}
			}
		}

		private static SolidColorBrush GetBorderBrush(string displayColor)
		{
			Color color;

			switch (displayColor)
			{
				case "yellow":
					color = Helper.ParseColor(0xB1A73C);
					break;
				case "blue":
					color = Helper.ParseColor(0x6BA9BA);
					break;
				case "orange":
					color = Helper.ParseColor(0xB07B38);
					break;
				case "green":
					color = Helper.ParseColor(0x87A73D);
					break;
				case "brown":
				default:
					color = Helper.ParseColor(0x7A5F45);
					break;
			}

			return new SolidColorBrush(color);
		}

		private string SetWeaponElement(IDictionary<string, FloatMinMax> attributes)
		{
			if (attributes != null)
			{
				foreach (var k in attributes.Keys)
				{
					if (weaponElements.ContainsKey(k))
					{
						return weaponElements[k];
					}
				}
			}

			return null;
		}

		protected virtual void SetOffset(ItemSlot itemSlot) { }
	}

	public class HeroItemViewModel : ItemViewModel
	{
		public HeroItemViewModel(Item item)
			: base(item)
		{
		}

		protected override void SetOffset(ItemSlot itemSlot)
		{
			Thickness slotffset = new Thickness(), iconOffset = new Thickness();
			double slotWidth = 0, slotHeight = 0, iconWidth = 0, iconHeight = 0;

			switch (itemSlot)
			{
				case ItemSlot.Head:
					slotffset = new Thickness(196, 20, 0, 0);
					iconOffset = new Thickness(0, -31, 0, 0);
					slotWidth = 64;
					slotHeight = 64;
					iconWidth = 64;
					iconHeight = 128;
					break;
				case ItemSlot.Torso:
					slotffset = new Thickness(188, 90, 0, 0);
					iconOffset = new Thickness(0, -25, 0, 0);
					slotWidth = 80;
					slotHeight = 113;
					iconWidth = 82;
					iconHeight = 164;
					break;
				case ItemSlot.Feet:
					slotffset = new Thickness(196, 339, 0, 0);
					iconOffset = new Thickness(0, -20, 0, 0);
					slotWidth = 64;
					slotHeight = 86;
					iconWidth = 64;
					iconHeight = 128;
					break;
				case ItemSlot.Hands:
					slotffset = new Thickness(88, 143, 0, 0);
					iconOffset = new Thickness(0, -20, 0, 0);
					slotWidth = 64;
					slotHeight = 86;
					iconWidth = 64;
					iconHeight = 128;
					break;
				case ItemSlot.Shoulders:
					slotffset = new Thickness(114, 44, 0, 0);
					iconOffset = new Thickness(0, -20, 0, 0);
					slotWidth = 64;
					slotHeight = 86;
					iconWidth = 64;
					iconHeight = 128;
					break;
				case ItemSlot.Legs:
					slotffset = new Thickness(196, 247, 0, 0);
					iconOffset = new Thickness(0, -20, 0, 0);
					slotWidth = 64;
					slotHeight = 86;
					iconWidth = 64;
					iconHeight = 128;
					break;
				case ItemSlot.Bracers:
					slotffset = new Thickness(304, 143, 0, 0);
					iconOffset = new Thickness(0, -20, 0, 0);
					slotWidth = 64;
					slotHeight = 86;
					iconWidth = 64;
					iconHeight = 128;
					break;
				case ItemSlot.MainHand:
					slotffset = new Thickness(88, 298, 0, 0);
					slotWidth = iconWidth = 64;
					slotHeight = iconHeight = 128;
					break;
				case ItemSlot.OffHand:
					slotffset = new Thickness(304, 298, 0, 0);
					slotWidth = iconWidth = 64;
					slotHeight = iconHeight = 128;
					break;
				case ItemSlot.Waist:
					slotffset = new Thickness(188, 209, 0, 0);
					iconOffset = new Thickness(0, -15, 0, 0);
					slotWidth = 80;
					slotHeight = 32;
					iconWidth = 64;
					iconHeight = 64;
					break;
				case ItemSlot.RightFinger:
					slotffset = new Thickness(100, 243, 0, 0);
					iconOffset = new Thickness(0, -12, 0, 0);
					slotWidth = 40;
					slotHeight = 40;
					iconWidth = 64;
					iconHeight = 64;
					break;
				case ItemSlot.LeftFinger:
					slotffset = new Thickness(316, 243, 0, 0);
					iconOffset = new Thickness(0, -12, 0, 0);
					slotWidth = 40;
					slotHeight = 40;
					iconWidth = 64;
					iconHeight = 64;
					break;
				case ItemSlot.Neck:
					slotffset = new Thickness(280, 64, 0, 0);
					slotWidth = 54;
					slotHeight = 54;
					iconWidth = 52;
					iconHeight = 52;
					break;
				default:
					break;
			}

			this.SlotOffset = slotffset;
			this.SlotWidth = slotWidth;
			this.SlotHeight = slotHeight;
			this.IconOffset = iconOffset;
			this.IconWidth = iconWidth;
			this.IconHeight = iconHeight;
		}
	}

	public class FollowerItemViewModel : ItemViewModel
	{
		public FollowerItemViewModel(Item item = null)
			: base(item)
		{
		}

		protected override void SetOffset(ItemSlot itemSlot)
		{
			Thickness slotffset = new Thickness(), iconOffset = new Thickness();
			double slotWidth = 0, slotHeight = 0, iconWidth = 0, iconHeight = 0;

			switch (itemSlot)
			{
				case ItemSlot.Special:
					slotffset = new Thickness(146, 49, 0, 0);
					slotWidth = 64;
					slotHeight = 64;
					iconWidth = 64;
					iconHeight = 64;
					break;
				case ItemSlot.MainHand:
					slotffset = new Thickness(239, 43, 0, 0);
					slotWidth = 64;
					slotHeight = 128;
					iconWidth = 64;
					iconHeight = 128;
					break;
				case ItemSlot.OffHand:
					slotffset = new Thickness(405, 43, 0, 0);
					slotWidth = 64;
					slotHeight = 128;
					iconWidth = 64;
					iconHeight = 128;
					break;
				case ItemSlot.RightFinger:
					slotffset = new Thickness(310, 115, 0, 0);
					iconOffset = new Thickness(0, -12, 0, 0);
					slotWidth = 40;
					slotHeight = 40;
					iconWidth = 64;
					iconHeight = 64;
					break;
				case ItemSlot.LeftFinger:
					slotffset = new Thickness(358, 115, 0, 0);
					iconOffset = new Thickness(0, -12, 0, 0);
					slotWidth = 40;
					slotHeight = 40;
					iconWidth = 64;
					iconHeight = 64;
					break;
				case ItemSlot.Neck:
					slotffset = new Thickness(329, 53, 0, 0);
					slotWidth = 54;
					slotHeight = 54;
					iconWidth = 52;
					iconHeight = 52;
					break;
				default:
					break;
			}

			this.SlotOffset = slotffset;
			this.SlotWidth = slotWidth;
			this.SlotHeight = slotHeight;
			this.IconOffset = iconOffset;
			this.IconWidth = iconWidth;
			this.IconHeight = iconHeight;
		}
	}
}
